package com.company.juc;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class MyThreadPoll extends ThreadPoolExecutor {
    /**
     * 线程池内部使用一个变量维护两个值：运行状态(runState)和线程数量 (workerCount)。
     * 在具体实现中，线程池将运行状态(runState)、线程数量 (workerCount)两个关键参数的维护放在了一起，
     * 如下代码所示：这是典型的位图控制模式！！！
     */
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
    private static int runStateOf(int c)     { return c & ~CAPACITY; } //计算当前运行状态
    private static int workerCountOf(int c)  { return c & CAPACITY; }  //计算当前线程数量
    private static int ctlOf(int rs, int wc) { return rs | wc; }   //通过状态和线程数生成ctl

    /**
        一些判断线程运行状态的API
     */
    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }
    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }
    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }

    /**
     * 一些CAS操作的API
     */
    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }
    private boolean compareAndDecrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect - 1);
    }
    private void decrementWorkerCount() {
        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
    }




    /**
     * ThreadPoolExecutor 定义了 5 种运行状态：
     * RUNNING	能接受新提交的任务，并且也能处理阻塞队列中的任务
     * SHUTDOWN	关闭状态，不再接受新提交的任务，但却可以继续处理阻塞队列中已保存的任务
     * STOP	不能接受新任务，也不处理队列中的任务，会中断正在处理任务的线程
     * TIDYING	所有的任务都已终止了，有效线程数为 0
     * TERMINATED	在 terminated() 方法执行后进入该状态
     */
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

    /**
     * 存放任务的阻塞队列，被提交但尚未被执行的任务
     */
    private final BlockingQueue<Runnable> workQueue;

    /**
     *  用于设置创建线程的工厂，可以给创建的线程设置有意义的名字，可方便排查问题
     */
    private volatile ThreadFactory threadFactory;
    /**
     * 线程池中非核心线程空闲后的存活时间（表示线程没有任务执行时最多保持多久时间会终止）
     */
    private volatile long keepAliveTime;
    /**
     * 核心线程是否在空闲时销毁
     */
    private volatile boolean allowCoreThreadTimeOut;
    /**
     * 线程池中的常驻核心线程数
     */
    private volatile int corePoolSize;
    /**
     * 线程池最大线程数大小，该值必须大于等于 1
     */
    private volatile int maximumPoolSize;

    /**
     * 拒绝策略，表示当等待队列满了且工作线程大于等于线程池的最大线程数（maximumPoolSize）时
     * 如何来拒绝请求执行的线程的策略，主要有四种类型：
     *   AbortPolicy ——直接抛出 RegectedExcutionException 异常阻止系统正常进行，默认策略
     *   DiscardPolicy ——直接丢弃任务，不予任何处理也不抛出异常，如果允许任务丢失，这是最好的一种方案
     *   DiscardOldestPolicy ——抛弃队列中等待最久的任务，然后把当前任务加入队列中尝试再次提交当前任务
     *   CallerRunsPolicy ——交给线程池调用所在的线程进行处理，“调用者运行”的一种调节机制，该策略既不会抛弃任务，
     *                      也不会抛出异常，而是将某些任务回退到调用者，从而降低新任务的流量
     */
    private volatile RejectedExecutionHandler handler;
    private static final RejectedExecutionHandler defaultHandler =
            new ThreadPoolExecutor.AbortPolicy();

    private final ReentrantLock mainLock = new ReentrantLock();
    private final HashSet<Worker> workers = new HashSet<Worker>();
    private final Condition termination = mainLock.newCondition();
    private int largestPoolSize;
    private long completedTaskCount;
    /**
     * 销毁线程池相关参数
     */
    private static final RuntimePermission shutdownPerm =
            new RuntimePermission("modifyThread");
    /* The context to be used when executing the finalizer, or null. */
    private final AccessControlContext acc;

    public MyThreadPoll(int corePoolSize,
                        int maximumPoolSize,
                        long keepAliveTime,
                        TimeUnit unit,
                        BlockingQueue<Runnable> workQueue,
                        ThreadFactory threadFactory,
                        RejectedExecutionHandler handler) {
        super( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

    @Override
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        /*如果 workerCount < corePoolSize，则创建并启动一个线程来执行新提交的任务。*/
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        /*如果 workerCount >= corePoolSize，且线程池内的阻塞队列未满，则将任务添加到该阻塞队列中*/
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            /*线程池运行状态，如果不是 RUNNING，则直接拒绝，线程池要保证在 RUNNING 的状态下执行任务。*/
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        /*如果 workerCount >= maximumPoolSize，并且线程池内的阻塞队列已满，(offer返回false)
        则根据拒绝策略来处理该任务，默认的处理方式是直接抛异常。*/
        else if (!addWorker(command, false))
            reject(command);
    }

    @Override
    public void shutdown() {

    }

    @Override
    public List<Runnable> shutdownNow() {
        return null;
    }

    @Override
    public boolean isShutdown() {
        return false;
    }

    @Override
    public boolean isTerminated() {
        return false;
    }

    @Override
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        return false;
    }




    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }
    private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            //todo 自旋+CAS从workQueue等待队列中取出队首的任务
            boolean timed = allowCoreThreadTimeOut || workers.size() > corePoolSize;
            try {
                Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

    //从当前待完成任务Set（workers）中移除worker,并且将已完成任务数加一
    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        //...
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }
        //...
    }

    //运行传入的worker(任务+线程)，成功完成任务则将该worker从当前任务集合中移出
    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                if ((runStateAtLeast(ctl.get(), STOP) ||
                        (Thread.interrupted() &&
                                runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                    wt.interrupt();
                try {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);  //获取不到任务时，主动回收自己
        }
    }

    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&
                    ! (rs == SHUTDOWN &&
                            firstTask == null &&
                            ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                        wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());

                    if (rs < SHUTDOWN ||
                            (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

    private void addWorkerFailed(Worker w) {

    }


    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

    /**
     * Worker 这个工作线程，实现了 Runnable 接口，并持有一个线程 thread，一个初始化的任务 firstTask。
     * thread是在调用构造方法时通过 ThreadFactory 来创建的线程，可以用来执行任务；
     * firstTask 用它来保存传入的第一个任务，这个任务可以有也可以为 null。
     * 如果这个值是非空的，那么线程就会在启动初期立即执行这个任务，也就对应核心线程创建时的情况；
     * 如果这个值是 null，那么就需要创建一个线程去执行任务列表（workQueue）中的任务，也就是非核心线程的创建。
     */
    private final class Worker
            extends AbstractQueuedSynchronizer
            implements Runnable
    {
        private static final long serialVersionUID = 6138294804551838833L;

        final Thread thread;//Worker持有的线程
        Runnable firstTask;//初始化的任务，可以为null
        volatile long completedTasks;  //线程任务计数器

        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

        /** Delegates main run loop to outer runWorker  */
        public void run() {
            runWorker(this);
        }

        // Lock methods
        //
        // The value 0 represents the unlocked state.
        // The value 1 represents the locked state.

        protected boolean isHeldExclusively() {
            return getState() != 0;
        }

        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        public void lock()        { acquire(1); }
        public boolean tryLock()  { return tryAcquire(1); }
        public void unlock()      { release(1); }
        public boolean isLocked() { return isHeldExclusively(); }

        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }
}
